﻿using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TresEnRaya.Data
{
    public enum EstadoPartida
    {
        EnJuego=0,
        Gana1,
        Gana2,
        Empate
    }

    public class Partida : TableEntity
    {
        public const int Dimension = 3;
        public Partida()
        {
        }

        public Partida(string pais, string id)
        {
            PartitionKey = pais;
            RowKey = id;
            _tablero = new char[Dimension * Dimension];
            for (int i = 0; i < _tablero.Length; i++)
            {
                _tablero[i] = ' ';
            }
        }

        public string Pais { get { return PartitionKey; } }
        public string Id { get { return RowKey; } }
        public Jugador Jugador1 { get; set; }
        public Jugador Jugador2 { get; set; }
        public int Turno { get; set; }
        public EstadoPartida Estado { get; set; }

        public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
        {
            var context = base.WriteEntity(operationContext);
            context.Remove("Jugador1");
            context.Add("Jugador1Nombre", EntityProperty.GeneratePropertyForString(Jugador1.Nombre));
            context.Add("Jugador1Id", EntityProperty.GeneratePropertyForString(Jugador1.Id));
            context.Remove("Jugador2");
            context.Add("Jugador2Nombre", EntityProperty.GeneratePropertyForString(Jugador2.Nombre));
            context.Add("Jugador2Id", EntityProperty.GeneratePropertyForString(Jugador2.Id));
            return context;
        }

        public override void ReadEntity(IDictionary<string, EntityProperty> properties,
            OperationContext operationContext)
        {
            Jugador1 = new Jugador(this.Pais,
                properties["Jugador1Nombre"].StringValue,
                properties["Jugador1Id"].StringValue);
            Jugador2 = new Jugador(this.Pais,
                properties["Jugador2Nombre"].StringValue,
                properties["Jugador2Id"].StringValue);
            base.ReadEntity(properties, operationContext);
        }

        char[] _tablero;
        public string Tablero
        {
            get
            {
                return new string(_tablero);
            }
            set
            {
                _tablero = value.ToCharArray();
            }
        }

        public bool Marcar(int x, int y, int jugador)
        {
            if (Estado == EstadoPartida.EnJuego)
            {
                var posicion = Dimension * x + y;
                if (jugador == Turno)
                {
                    if (_tablero[posicion] == ' ')
                    {
                        var valor = Turno == 0 ? 'O' : 'X';
                        _tablero[Dimension * x + y] = valor;
                        Turno = Turno == 0 ? 1 : 0;
                        return ComprobarFinal();
                    }
                    else
                    {
                        throw new InvalidOperationException("La casilla está ocupada");
                    }
                }
                else
                {
                    throw new InvalidOperationException("No es tu turno");
                }
            }
            else
            {
                throw new InvalidCastException("El juego ha acabado");
            }
        }

        public char Valor(int x, int y)
        {
            return _tablero[Dimension * x + y];
        }

        bool ComprobarFinal()
        {
            int[] jugadas = new int[Partida.Dimension * 2 + 2];

            for (int i = 0; i < Partida.Dimension; i++)
            {
                for (int j = 0; j < Partida.Dimension; j++)
                {
                    var v = Valor(i, j);
                    int sum = 0;
                    if (v == 'X')
                    {
                        sum = -1;
                    }
                    else if (v == 'O')
                    {
                        sum = 1;
                    }
                    jugadas[i] += sum;
                    jugadas[Partida.Dimension + j] += sum;
                    if (i == j)
                    {
                        jugadas[Partida.Dimension * 2] += sum;
                    }
                    if (i + j == Partida.Dimension - 1)
                    {
                        jugadas[Partida.Dimension * 2 + 1] += sum;
                    }
                }
            }
            if (jugadas.Count((x) => x == 3) > 0)
            {
                Estado = EstadoPartida.Gana1;
            }
            else if (jugadas.Count((x) => x == -3) > 0)
            {
                Estado = EstadoPartida.Gana2;
            }
            else if (!Tablero.Contains(' '))
            {
                Estado = EstadoPartida.Empate;
            }

            return Estado != EstadoPartida.EnJuego;
        }
    }
   
}